{
 "cells": [
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "# How to Automate Feature Engineering with AI\n",
    "\n",
    "In this tutorial, we will learn how to automate feature engineering with AI using the Feature Engineering Agent. The Feature Engineering Agent is a powerful tool that can automatically generate features for your data. It analyzes your data and determines necessary actions to prepare it for machine learning including:\n",
    "\n",
    "- One Hot Encoding\n",
    "- Missing Value Imputation\n",
    "- Outlier Detection\n",
    "\n",
    "\n",
    "### Want To Become A Full-Stack Generative AI Data Scientist?\n",
    "\n",
    "![Generative AI Data Scientist](../img/become_a_generative_ai_data_scientist.jpg)\n",
    "\n",
    "I teach Generative AI Data Science to help you build AI-powered data science apps. [**Register for my next Generative AI for Data Scientists workshop here.**](https://learn.business-science.io/ai-register)\n"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "# Table of Contents\n",
    "\n",
    "1. [How to Automate Feature Engineering with AI](#how-to-automate-feature-engineering-with-ai)\n",
    "2. [Load Libraries](#load-libraries)\n",
    "3. [Setup AI and Logging](#setup-ai-and-logging)\n",
    "4. [Load a Dataset](#load-a-dataset)\n",
    "5. [Create The Agent](#create-the-agent)\n",
    "6. [Response](#response)\n",
    "7. [The feature engineering recipe](#the-feature-engineering-recipe)\n",
    "8. [Feature Engineer Function](#feature-engineer-function)\n",
    "9. [Feature Engineered Data As Pandas Data Frame](#feature-engineered-data-as-pandas-data-frame)\n",
    "10. [Free Generative AI Data Science Workshop](#free-generative-ai-data-science-workshop)"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "### Load Libraries"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 1,
   "metadata": {},
   "outputs": [],
   "source": [
    "# * Libraries\n",
    "\n",
    "from langchain_openai import ChatOpenAI\n",
    "import os\n",
    "import yaml\n",
    "import pandas as pd\n",
    "from pprint import pprint\n",
    "\n",
    "from ai_data_science_team.agents import FeatureEngineeringAgent"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "### Setup AI and Logging\n",
    "\n",
    "This section of code sets up the LLM inputs and the logging information. Logging is used to store AI-generated code and files during the AI Data Science Teams processing of files. \n",
    "\n",
    "*Important Note:* This example uses OpenAI's API. But any LLM can be used such as Anthropic or local LLMs with Ollama."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 2,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "ChatOpenAI(client=<openai.resources.chat.completions.Completions object at 0x7f8fb07e8e80>, async_client=<openai.resources.chat.completions.AsyncCompletions object at 0x7f8fb07e8610>, root_client=<openai.OpenAI object at 0x7f8fb0acfe50>, root_async_client=<openai.AsyncOpenAI object at 0x7f8fb07e8e20>, model_name='gpt-4o-mini', model_kwargs={}, openai_api_key=SecretStr('**********'))"
      ]
     },
     "execution_count": 2,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "# * Setup\n",
    "\n",
    "MODEL    = \"gpt-4o-mini\"\n",
    "LOG      = True\n",
    "LOG_PATH = os.path.join(os.getcwd(), \"logs/\")\n",
    "\n",
    "os.environ[\"OPENAI_API_KEY\"] = yaml.safe_load(open('../credentials.yml'))['openai']\n",
    "\n",
    "llm = ChatOpenAI(model = MODEL)\n",
    "\n",
    "llm\n"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "### Load a Dataset\n",
    "\n",
    "Next, let's load a customer churn data set that we will clean up. "
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 3,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/html": [
       "<div>\n",
       "<style scoped>\n",
       "    .dataframe tbody tr th:only-of-type {\n",
       "        vertical-align: middle;\n",
       "    }\n",
       "\n",
       "    .dataframe tbody tr th {\n",
       "        vertical-align: top;\n",
       "    }\n",
       "\n",
       "    .dataframe thead th {\n",
       "        text-align: right;\n",
       "    }\n",
       "</style>\n",
       "<table border=\"1\" class=\"dataframe\">\n",
       "  <thead>\n",
       "    <tr style=\"text-align: right;\">\n",
       "      <th></th>\n",
       "      <th>customerID</th>\n",
       "      <th>gender</th>\n",
       "      <th>SeniorCitizen</th>\n",
       "      <th>Partner</th>\n",
       "      <th>Dependents</th>\n",
       "      <th>tenure</th>\n",
       "      <th>PhoneService</th>\n",
       "      <th>MultipleLines</th>\n",
       "      <th>InternetService</th>\n",
       "      <th>OnlineSecurity</th>\n",
       "      <th>...</th>\n",
       "      <th>DeviceProtection</th>\n",
       "      <th>TechSupport</th>\n",
       "      <th>StreamingTV</th>\n",
       "      <th>StreamingMovies</th>\n",
       "      <th>Contract</th>\n",
       "      <th>PaperlessBilling</th>\n",
       "      <th>PaymentMethod</th>\n",
       "      <th>MonthlyCharges</th>\n",
       "      <th>TotalCharges</th>\n",
       "      <th>Churn</th>\n",
       "    </tr>\n",
       "  </thead>\n",
       "  <tbody>\n",
       "    <tr>\n",
       "      <th>0</th>\n",
       "      <td>7590-VHVEG</td>\n",
       "      <td>Female</td>\n",
       "      <td>0</td>\n",
       "      <td>Yes</td>\n",
       "      <td>No</td>\n",
       "      <td>1</td>\n",
       "      <td>No</td>\n",
       "      <td>No phone service</td>\n",
       "      <td>DSL</td>\n",
       "      <td>No</td>\n",
       "      <td>...</td>\n",
       "      <td>No</td>\n",
       "      <td>No</td>\n",
       "      <td>No</td>\n",
       "      <td>No</td>\n",
       "      <td>Month-to-month</td>\n",
       "      <td>Yes</td>\n",
       "      <td>Electronic check</td>\n",
       "      <td>29.85</td>\n",
       "      <td>29.85</td>\n",
       "      <td>No</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>1</th>\n",
       "      <td>5575-GNVDE</td>\n",
       "      <td>Male</td>\n",
       "      <td>0</td>\n",
       "      <td>No</td>\n",
       "      <td>No</td>\n",
       "      <td>34</td>\n",
       "      <td>Yes</td>\n",
       "      <td>No</td>\n",
       "      <td>DSL</td>\n",
       "      <td>Yes</td>\n",
       "      <td>...</td>\n",
       "      <td>Yes</td>\n",
       "      <td>No</td>\n",
       "      <td>No</td>\n",
       "      <td>No</td>\n",
       "      <td>One year</td>\n",
       "      <td>No</td>\n",
       "      <td>Mailed check</td>\n",
       "      <td>56.95</td>\n",
       "      <td>1889.5</td>\n",
       "      <td>No</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>2</th>\n",
       "      <td>3668-QPYBK</td>\n",
       "      <td>Male</td>\n",
       "      <td>0</td>\n",
       "      <td>No</td>\n",
       "      <td>No</td>\n",
       "      <td>2</td>\n",
       "      <td>Yes</td>\n",
       "      <td>No</td>\n",
       "      <td>DSL</td>\n",
       "      <td>Yes</td>\n",
       "      <td>...</td>\n",
       "      <td>No</td>\n",
       "      <td>No</td>\n",
       "      <td>No</td>\n",
       "      <td>No</td>\n",
       "      <td>Month-to-month</td>\n",
       "      <td>Yes</td>\n",
       "      <td>Mailed check</td>\n",
       "      <td>53.85</td>\n",
       "      <td>108.15</td>\n",
       "      <td>Yes</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>3</th>\n",
       "      <td>7795-CFOCW</td>\n",
       "      <td>Male</td>\n",
       "      <td>0</td>\n",
       "      <td>No</td>\n",
       "      <td>No</td>\n",
       "      <td>45</td>\n",
       "      <td>No</td>\n",
       "      <td>No phone service</td>\n",
       "      <td>DSL</td>\n",
       "      <td>Yes</td>\n",
       "      <td>...</td>\n",
       "      <td>Yes</td>\n",
       "      <td>Yes</td>\n",
       "      <td>No</td>\n",
       "      <td>No</td>\n",
       "      <td>One year</td>\n",
       "      <td>No</td>\n",
       "      <td>Bank transfer (automatic)</td>\n",
       "      <td>42.30</td>\n",
       "      <td>1840.75</td>\n",
       "      <td>No</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>4</th>\n",
       "      <td>9237-HQITU</td>\n",
       "      <td>Female</td>\n",
       "      <td>0</td>\n",
       "      <td>No</td>\n",
       "      <td>No</td>\n",
       "      <td>2</td>\n",
       "      <td>Yes</td>\n",
       "      <td>No</td>\n",
       "      <td>Fiber optic</td>\n",
       "      <td>No</td>\n",
       "      <td>...</td>\n",
       "      <td>No</td>\n",
       "      <td>No</td>\n",
       "      <td>No</td>\n",
       "      <td>No</td>\n",
       "      <td>Month-to-month</td>\n",
       "      <td>Yes</td>\n",
       "      <td>Electronic check</td>\n",
       "      <td>70.70</td>\n",
       "      <td>151.65</td>\n",
       "      <td>Yes</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>...</th>\n",
       "      <td>...</td>\n",
       "      <td>...</td>\n",
       "      <td>...</td>\n",
       "      <td>...</td>\n",
       "      <td>...</td>\n",
       "      <td>...</td>\n",
       "      <td>...</td>\n",
       "      <td>...</td>\n",
       "      <td>...</td>\n",
       "      <td>...</td>\n",
       "      <td>...</td>\n",
       "      <td>...</td>\n",
       "      <td>...</td>\n",
       "      <td>...</td>\n",
       "      <td>...</td>\n",
       "      <td>...</td>\n",
       "      <td>...</td>\n",
       "      <td>...</td>\n",
       "      <td>...</td>\n",
       "      <td>...</td>\n",
       "      <td>...</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>7038</th>\n",
       "      <td>6840-RESVB</td>\n",
       "      <td>Male</td>\n",
       "      <td>0</td>\n",
       "      <td>Yes</td>\n",
       "      <td>Yes</td>\n",
       "      <td>24</td>\n",
       "      <td>Yes</td>\n",
       "      <td>Yes</td>\n",
       "      <td>DSL</td>\n",
       "      <td>Yes</td>\n",
       "      <td>...</td>\n",
       "      <td>Yes</td>\n",
       "      <td>Yes</td>\n",
       "      <td>Yes</td>\n",
       "      <td>Yes</td>\n",
       "      <td>One year</td>\n",
       "      <td>Yes</td>\n",
       "      <td>Mailed check</td>\n",
       "      <td>84.80</td>\n",
       "      <td>1990.5</td>\n",
       "      <td>No</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>7039</th>\n",
       "      <td>2234-XADUH</td>\n",
       "      <td>Female</td>\n",
       "      <td>0</td>\n",
       "      <td>Yes</td>\n",
       "      <td>Yes</td>\n",
       "      <td>72</td>\n",
       "      <td>Yes</td>\n",
       "      <td>Yes</td>\n",
       "      <td>Fiber optic</td>\n",
       "      <td>No</td>\n",
       "      <td>...</td>\n",
       "      <td>Yes</td>\n",
       "      <td>No</td>\n",
       "      <td>Yes</td>\n",
       "      <td>Yes</td>\n",
       "      <td>One year</td>\n",
       "      <td>Yes</td>\n",
       "      <td>Credit card (automatic)</td>\n",
       "      <td>103.20</td>\n",
       "      <td>7362.9</td>\n",
       "      <td>No</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>7040</th>\n",
       "      <td>4801-JZAZL</td>\n",
       "      <td>Female</td>\n",
       "      <td>0</td>\n",
       "      <td>Yes</td>\n",
       "      <td>Yes</td>\n",
       "      <td>11</td>\n",
       "      <td>No</td>\n",
       "      <td>No phone service</td>\n",
       "      <td>DSL</td>\n",
       "      <td>Yes</td>\n",
       "      <td>...</td>\n",
       "      <td>No</td>\n",
       "      <td>No</td>\n",
       "      <td>No</td>\n",
       "      <td>No</td>\n",
       "      <td>Month-to-month</td>\n",
       "      <td>Yes</td>\n",
       "      <td>Electronic check</td>\n",
       "      <td>29.60</td>\n",
       "      <td>346.45</td>\n",
       "      <td>No</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>7041</th>\n",
       "      <td>8361-LTMKD</td>\n",
       "      <td>Male</td>\n",
       "      <td>1</td>\n",
       "      <td>Yes</td>\n",
       "      <td>No</td>\n",
       "      <td>4</td>\n",
       "      <td>Yes</td>\n",
       "      <td>Yes</td>\n",
       "      <td>Fiber optic</td>\n",
       "      <td>No</td>\n",
       "      <td>...</td>\n",
       "      <td>No</td>\n",
       "      <td>No</td>\n",
       "      <td>No</td>\n",
       "      <td>No</td>\n",
       "      <td>Month-to-month</td>\n",
       "      <td>Yes</td>\n",
       "      <td>Mailed check</td>\n",
       "      <td>74.40</td>\n",
       "      <td>306.6</td>\n",
       "      <td>Yes</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>7042</th>\n",
       "      <td>3186-AJIEK</td>\n",
       "      <td>Male</td>\n",
       "      <td>0</td>\n",
       "      <td>No</td>\n",
       "      <td>No</td>\n",
       "      <td>66</td>\n",
       "      <td>Yes</td>\n",
       "      <td>No</td>\n",
       "      <td>Fiber optic</td>\n",
       "      <td>Yes</td>\n",
       "      <td>...</td>\n",
       "      <td>Yes</td>\n",
       "      <td>Yes</td>\n",
       "      <td>Yes</td>\n",
       "      <td>Yes</td>\n",
       "      <td>Two year</td>\n",
       "      <td>Yes</td>\n",
       "      <td>Bank transfer (automatic)</td>\n",
       "      <td>105.65</td>\n",
       "      <td>6844.5</td>\n",
       "      <td>No</td>\n",
       "    </tr>\n",
       "  </tbody>\n",
       "</table>\n",
       "<p>7043 rows × 21 columns</p>\n",
       "</div>"
      ],
      "text/plain": [
       "      customerID  gender  SeniorCitizen Partner Dependents  tenure  \\\n",
       "0     7590-VHVEG  Female              0     Yes         No       1   \n",
       "1     5575-GNVDE    Male              0      No         No      34   \n",
       "2     3668-QPYBK    Male              0      No         No       2   \n",
       "3     7795-CFOCW    Male              0      No         No      45   \n",
       "4     9237-HQITU  Female              0      No         No       2   \n",
       "...          ...     ...            ...     ...        ...     ...   \n",
       "7038  6840-RESVB    Male              0     Yes        Yes      24   \n",
       "7039  2234-XADUH  Female              0     Yes        Yes      72   \n",
       "7040  4801-JZAZL  Female              0     Yes        Yes      11   \n",
       "7041  8361-LTMKD    Male              1     Yes         No       4   \n",
       "7042  3186-AJIEK    Male              0      No         No      66   \n",
       "\n",
       "     PhoneService     MultipleLines InternetService OnlineSecurity  ...  \\\n",
       "0              No  No phone service             DSL             No  ...   \n",
       "1             Yes                No             DSL            Yes  ...   \n",
       "2             Yes                No             DSL            Yes  ...   \n",
       "3              No  No phone service             DSL            Yes  ...   \n",
       "4             Yes                No     Fiber optic             No  ...   \n",
       "...           ...               ...             ...            ...  ...   \n",
       "7038          Yes               Yes             DSL            Yes  ...   \n",
       "7039          Yes               Yes     Fiber optic             No  ...   \n",
       "7040           No  No phone service             DSL            Yes  ...   \n",
       "7041          Yes               Yes     Fiber optic             No  ...   \n",
       "7042          Yes                No     Fiber optic            Yes  ...   \n",
       "\n",
       "     DeviceProtection TechSupport StreamingTV StreamingMovies        Contract  \\\n",
       "0                  No          No          No              No  Month-to-month   \n",
       "1                 Yes          No          No              No        One year   \n",
       "2                  No          No          No              No  Month-to-month   \n",
       "3                 Yes         Yes          No              No        One year   \n",
       "4                  No          No          No              No  Month-to-month   \n",
       "...               ...         ...         ...             ...             ...   \n",
       "7038              Yes         Yes         Yes             Yes        One year   \n",
       "7039              Yes          No         Yes             Yes        One year   \n",
       "7040               No          No          No              No  Month-to-month   \n",
       "7041               No          No          No              No  Month-to-month   \n",
       "7042              Yes         Yes         Yes             Yes        Two year   \n",
       "\n",
       "     PaperlessBilling              PaymentMethod MonthlyCharges  TotalCharges  \\\n",
       "0                 Yes           Electronic check          29.85         29.85   \n",
       "1                  No               Mailed check          56.95        1889.5   \n",
       "2                 Yes               Mailed check          53.85        108.15   \n",
       "3                  No  Bank transfer (automatic)          42.30       1840.75   \n",
       "4                 Yes           Electronic check          70.70        151.65   \n",
       "...               ...                        ...            ...           ...   \n",
       "7038              Yes               Mailed check          84.80        1990.5   \n",
       "7039              Yes    Credit card (automatic)         103.20        7362.9   \n",
       "7040              Yes           Electronic check          29.60        346.45   \n",
       "7041              Yes               Mailed check          74.40         306.6   \n",
       "7042              Yes  Bank transfer (automatic)         105.65        6844.5   \n",
       "\n",
       "     Churn  \n",
       "0       No  \n",
       "1       No  \n",
       "2      Yes  \n",
       "3       No  \n",
       "4      Yes  \n",
       "...    ...  \n",
       "7038    No  \n",
       "7039    No  \n",
       "7040    No  \n",
       "7041   Yes  \n",
       "7042    No  \n",
       "\n",
       "[7043 rows x 21 columns]"
      ]
     },
     "execution_count": 3,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "df = pd.read_csv(\"https://raw.githubusercontent.com/business-science/ai-data-science-team/refs/heads/master/data/churn_data.csv\")\n",
    "df"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "### Create The Agent\n",
    "\n",
    "Run this code to create the agent with `make_feature_engineering_agent()`."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 4,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "image/png": "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",
      "text/plain": [
       "<ai_data_science_team.agents.feature_engineering_agent.FeatureEngineeringAgent object at 0x7f8fb0b0d240>"
      ]
     },
     "execution_count": 4,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "feature_engineering_agent = FeatureEngineeringAgent(\n",
    "    model = llm, \n",
    "    log=LOG, \n",
    "    log_path=LOG_PATH\n",
    ")\n",
    "\n",
    "feature_engineering_agent"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "The main inputs to the Feature Engineering Agent are:\n",
    "\n",
    "- **data_raw**: The raw data to have engineered feature transformations applied.\n",
    "- **user_instructions**: The data cleaning agent will use these comments to modify the \"standard recipe\" (optional). See the documentation for the standard feature engineering steps that are evaluated for application by the LLM. \n",
    "- **target_variable**: The column name of the target variable (optional).\n",
    "- **max_retries**: Used to limit the number of attempts to fix the python code generated by the agent. Set this to 3 to limit to 3 attempts. \n",
    "- **retry_count**: Set this to 0. "
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "---FEATURE ENGINEERING AGENT----\n",
      "    * RECOMMEND FEATURE ENGINEERING STEPS\n",
      "    * CREATE FEATURE ENGINEERING CODE\n",
      "      File saved to: /Users/mdancho/Desktop/course_code/ai-data-science-team/logs/feature_engineer.py\n",
      "    * EXECUTING AGENT CODE\n",
      "'Churn'\n",
      "    * FIX AGENT CODE\n",
      "      retry_count:0\n",
      "      File saved to: /Users/mdancho/Desktop/course_code/ai-data-science-team/logs/feature_engineer.py\n",
      "    * EXECUTING AGENT CODE\n",
      "    * EXPLAIN AGENT CODE\n"
     ]
    }
   ],
   "source": [
    "feature_engineering_agent.invoke_agent(\n",
    "    data_raw=df,\n",
    "    user_instructions=\"Inspect the data. Make any new features and transformations that you think will be useful for predicting the target variable.\",\n",
    "    target_variable=\"Churn\",\n",
    "    max_retries=3,\n",
    "    retry_count=0,\n",
    ")"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "### Response\n",
    "\n",
    "The response produced contains everything we need to understand the data cleaning decisions made and get the cleaned dataset. "
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 6,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "['messages',\n",
       " 'user_instructions',\n",
       " 'recommended_steps',\n",
       " 'data_raw',\n",
       " 'data_engineered',\n",
       " 'target_variable',\n",
       " 'all_datasets_summary',\n",
       " 'feature_engineer_function',\n",
       " 'feature_engineer_function_path',\n",
       " 'feature_engineer_function_name',\n",
       " 'feature_engineer_error',\n",
       " 'max_retries',\n",
       " 'retry_count']"
      ]
     },
     "execution_count": 6,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "response = feature_engineering_agent.get_response()\n",
    "\n",
    "list(response.keys())"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "#### Feature Engineered Data"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 7,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/html": [
       "<div>\n",
       "<style scoped>\n",
       "    .dataframe tbody tr th:only-of-type {\n",
       "        vertical-align: middle;\n",
       "    }\n",
       "\n",
       "    .dataframe tbody tr th {\n",
       "        vertical-align: top;\n",
       "    }\n",
       "\n",
       "    .dataframe thead th {\n",
       "        text-align: right;\n",
       "    }\n",
       "</style>\n",
       "<table border=\"1\" class=\"dataframe\">\n",
       "  <thead>\n",
       "    <tr style=\"text-align: right;\">\n",
       "      <th></th>\n",
       "      <th>SeniorCitizen</th>\n",
       "      <th>tenure</th>\n",
       "      <th>MonthlyCharges</th>\n",
       "      <th>TotalCharges</th>\n",
       "      <th>gender_Male</th>\n",
       "      <th>Partner_Yes</th>\n",
       "      <th>Dependents_Yes</th>\n",
       "      <th>PhoneService_Yes</th>\n",
       "      <th>MultipleLines_No phone service</th>\n",
       "      <th>MultipleLines_Yes</th>\n",
       "      <th>...</th>\n",
       "      <th>StreamingMovies_No internet service</th>\n",
       "      <th>StreamingMovies_Yes</th>\n",
       "      <th>Contract_One year</th>\n",
       "      <th>Contract_Two year</th>\n",
       "      <th>PaperlessBilling_Yes</th>\n",
       "      <th>PaymentMethod_Credit card (automatic)</th>\n",
       "      <th>PaymentMethod_Electronic check</th>\n",
       "      <th>PaymentMethod_Mailed check</th>\n",
       "      <th>Churn_Yes</th>\n",
       "      <th>MonthlyCharges_per_tenure</th>\n",
       "    </tr>\n",
       "  </thead>\n",
       "  <tbody>\n",
       "    <tr>\n",
       "      <th>0</th>\n",
       "      <td>0</td>\n",
       "      <td>1</td>\n",
       "      <td>29.85</td>\n",
       "      <td>29.85</td>\n",
       "      <td>False</td>\n",
       "      <td>True</td>\n",
       "      <td>False</td>\n",
       "      <td>False</td>\n",
       "      <td>True</td>\n",
       "      <td>False</td>\n",
       "      <td>...</td>\n",
       "      <td>False</td>\n",
       "      <td>False</td>\n",
       "      <td>False</td>\n",
       "      <td>False</td>\n",
       "      <td>True</td>\n",
       "      <td>False</td>\n",
       "      <td>True</td>\n",
       "      <td>False</td>\n",
       "      <td>False</td>\n",
       "      <td>14.925000</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>1</th>\n",
       "      <td>0</td>\n",
       "      <td>34</td>\n",
       "      <td>56.95</td>\n",
       "      <td>1889.50</td>\n",
       "      <td>True</td>\n",
       "      <td>False</td>\n",
       "      <td>False</td>\n",
       "      <td>True</td>\n",
       "      <td>False</td>\n",
       "      <td>False</td>\n",
       "      <td>...</td>\n",
       "      <td>False</td>\n",
       "      <td>False</td>\n",
       "      <td>True</td>\n",
       "      <td>False</td>\n",
       "      <td>False</td>\n",
       "      <td>False</td>\n",
       "      <td>False</td>\n",
       "      <td>True</td>\n",
       "      <td>False</td>\n",
       "      <td>1.627143</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>2</th>\n",
       "      <td>0</td>\n",
       "      <td>2</td>\n",
       "      <td>53.85</td>\n",
       "      <td>108.15</td>\n",
       "      <td>True</td>\n",
       "      <td>False</td>\n",
       "      <td>False</td>\n",
       "      <td>True</td>\n",
       "      <td>False</td>\n",
       "      <td>False</td>\n",
       "      <td>...</td>\n",
       "      <td>False</td>\n",
       "      <td>False</td>\n",
       "      <td>False</td>\n",
       "      <td>False</td>\n",
       "      <td>True</td>\n",
       "      <td>False</td>\n",
       "      <td>False</td>\n",
       "      <td>True</td>\n",
       "      <td>True</td>\n",
       "      <td>17.950000</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>3</th>\n",
       "      <td>0</td>\n",
       "      <td>45</td>\n",
       "      <td>42.30</td>\n",
       "      <td>1840.75</td>\n",
       "      <td>True</td>\n",
       "      <td>False</td>\n",
       "      <td>False</td>\n",
       "      <td>False</td>\n",
       "      <td>True</td>\n",
       "      <td>False</td>\n",
       "      <td>...</td>\n",
       "      <td>False</td>\n",
       "      <td>False</td>\n",
       "      <td>True</td>\n",
       "      <td>False</td>\n",
       "      <td>False</td>\n",
       "      <td>False</td>\n",
       "      <td>False</td>\n",
       "      <td>False</td>\n",
       "      <td>False</td>\n",
       "      <td>0.919565</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>4</th>\n",
       "      <td>0</td>\n",
       "      <td>2</td>\n",
       "      <td>70.70</td>\n",
       "      <td>151.65</td>\n",
       "      <td>False</td>\n",
       "      <td>False</td>\n",
       "      <td>False</td>\n",
       "      <td>True</td>\n",
       "      <td>False</td>\n",
       "      <td>False</td>\n",
       "      <td>...</td>\n",
       "      <td>False</td>\n",
       "      <td>False</td>\n",
       "      <td>False</td>\n",
       "      <td>False</td>\n",
       "      <td>True</td>\n",
       "      <td>False</td>\n",
       "      <td>True</td>\n",
       "      <td>False</td>\n",
       "      <td>True</td>\n",
       "      <td>23.566667</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>...</th>\n",
       "      <td>...</td>\n",
       "      <td>...</td>\n",
       "      <td>...</td>\n",
       "      <td>...</td>\n",
       "      <td>...</td>\n",
       "      <td>...</td>\n",
       "      <td>...</td>\n",
       "      <td>...</td>\n",
       "      <td>...</td>\n",
       "      <td>...</td>\n",
       "      <td>...</td>\n",
       "      <td>...</td>\n",
       "      <td>...</td>\n",
       "      <td>...</td>\n",
       "      <td>...</td>\n",
       "      <td>...</td>\n",
       "      <td>...</td>\n",
       "      <td>...</td>\n",
       "      <td>...</td>\n",
       "      <td>...</td>\n",
       "      <td>...</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>7038</th>\n",
       "      <td>0</td>\n",
       "      <td>24</td>\n",
       "      <td>84.80</td>\n",
       "      <td>1990.50</td>\n",
       "      <td>True</td>\n",
       "      <td>True</td>\n",
       "      <td>True</td>\n",
       "      <td>True</td>\n",
       "      <td>False</td>\n",
       "      <td>True</td>\n",
       "      <td>...</td>\n",
       "      <td>False</td>\n",
       "      <td>True</td>\n",
       "      <td>True</td>\n",
       "      <td>False</td>\n",
       "      <td>True</td>\n",
       "      <td>False</td>\n",
       "      <td>False</td>\n",
       "      <td>True</td>\n",
       "      <td>False</td>\n",
       "      <td>3.392000</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>7039</th>\n",
       "      <td>0</td>\n",
       "      <td>72</td>\n",
       "      <td>103.20</td>\n",
       "      <td>7362.90</td>\n",
       "      <td>False</td>\n",
       "      <td>True</td>\n",
       "      <td>True</td>\n",
       "      <td>True</td>\n",
       "      <td>False</td>\n",
       "      <td>True</td>\n",
       "      <td>...</td>\n",
       "      <td>False</td>\n",
       "      <td>True</td>\n",
       "      <td>True</td>\n",
       "      <td>False</td>\n",
       "      <td>True</td>\n",
       "      <td>True</td>\n",
       "      <td>False</td>\n",
       "      <td>False</td>\n",
       "      <td>False</td>\n",
       "      <td>1.413699</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>7040</th>\n",
       "      <td>0</td>\n",
       "      <td>11</td>\n",
       "      <td>29.60</td>\n",
       "      <td>346.45</td>\n",
       "      <td>False</td>\n",
       "      <td>True</td>\n",
       "      <td>True</td>\n",
       "      <td>False</td>\n",
       "      <td>True</td>\n",
       "      <td>False</td>\n",
       "      <td>...</td>\n",
       "      <td>False</td>\n",
       "      <td>False</td>\n",
       "      <td>False</td>\n",
       "      <td>False</td>\n",
       "      <td>True</td>\n",
       "      <td>False</td>\n",
       "      <td>True</td>\n",
       "      <td>False</td>\n",
       "      <td>False</td>\n",
       "      <td>2.466667</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>7041</th>\n",
       "      <td>1</td>\n",
       "      <td>4</td>\n",
       "      <td>74.40</td>\n",
       "      <td>306.60</td>\n",
       "      <td>True</td>\n",
       "      <td>True</td>\n",
       "      <td>False</td>\n",
       "      <td>True</td>\n",
       "      <td>False</td>\n",
       "      <td>True</td>\n",
       "      <td>...</td>\n",
       "      <td>False</td>\n",
       "      <td>False</td>\n",
       "      <td>False</td>\n",
       "      <td>False</td>\n",
       "      <td>True</td>\n",
       "      <td>False</td>\n",
       "      <td>False</td>\n",
       "      <td>True</td>\n",
       "      <td>True</td>\n",
       "      <td>14.880000</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>7042</th>\n",
       "      <td>0</td>\n",
       "      <td>66</td>\n",
       "      <td>105.65</td>\n",
       "      <td>6844.50</td>\n",
       "      <td>True</td>\n",
       "      <td>False</td>\n",
       "      <td>False</td>\n",
       "      <td>True</td>\n",
       "      <td>False</td>\n",
       "      <td>False</td>\n",
       "      <td>...</td>\n",
       "      <td>False</td>\n",
       "      <td>True</td>\n",
       "      <td>False</td>\n",
       "      <td>True</td>\n",
       "      <td>True</td>\n",
       "      <td>False</td>\n",
       "      <td>False</td>\n",
       "      <td>False</td>\n",
       "      <td>False</td>\n",
       "      <td>1.576866</td>\n",
       "    </tr>\n",
       "  </tbody>\n",
       "</table>\n",
       "<p>7043 rows × 32 columns</p>\n",
       "</div>"
      ],
      "text/plain": [
       "      SeniorCitizen  tenure  MonthlyCharges  TotalCharges  gender_Male  \\\n",
       "0                 0       1           29.85         29.85        False   \n",
       "1                 0      34           56.95       1889.50         True   \n",
       "2                 0       2           53.85        108.15         True   \n",
       "3                 0      45           42.30       1840.75         True   \n",
       "4                 0       2           70.70        151.65        False   \n",
       "...             ...     ...             ...           ...          ...   \n",
       "7038              0      24           84.80       1990.50         True   \n",
       "7039              0      72          103.20       7362.90        False   \n",
       "7040              0      11           29.60        346.45        False   \n",
       "7041              1       4           74.40        306.60         True   \n",
       "7042              0      66          105.65       6844.50         True   \n",
       "\n",
       "      Partner_Yes  Dependents_Yes  PhoneService_Yes  \\\n",
       "0            True           False             False   \n",
       "1           False           False              True   \n",
       "2           False           False              True   \n",
       "3           False           False             False   \n",
       "4           False           False              True   \n",
       "...           ...             ...               ...   \n",
       "7038         True            True              True   \n",
       "7039         True            True              True   \n",
       "7040         True            True             False   \n",
       "7041         True           False              True   \n",
       "7042        False           False              True   \n",
       "\n",
       "      MultipleLines_No phone service  MultipleLines_Yes  ...  \\\n",
       "0                               True              False  ...   \n",
       "1                              False              False  ...   \n",
       "2                              False              False  ...   \n",
       "3                               True              False  ...   \n",
       "4                              False              False  ...   \n",
       "...                              ...                ...  ...   \n",
       "7038                           False               True  ...   \n",
       "7039                           False               True  ...   \n",
       "7040                            True              False  ...   \n",
       "7041                           False               True  ...   \n",
       "7042                           False              False  ...   \n",
       "\n",
       "      StreamingMovies_No internet service  StreamingMovies_Yes  \\\n",
       "0                                   False                False   \n",
       "1                                   False                False   \n",
       "2                                   False                False   \n",
       "3                                   False                False   \n",
       "4                                   False                False   \n",
       "...                                   ...                  ...   \n",
       "7038                                False                 True   \n",
       "7039                                False                 True   \n",
       "7040                                False                False   \n",
       "7041                                False                False   \n",
       "7042                                False                 True   \n",
       "\n",
       "      Contract_One year  Contract_Two year  PaperlessBilling_Yes  \\\n",
       "0                 False              False                  True   \n",
       "1                  True              False                 False   \n",
       "2                 False              False                  True   \n",
       "3                  True              False                 False   \n",
       "4                 False              False                  True   \n",
       "...                 ...                ...                   ...   \n",
       "7038               True              False                  True   \n",
       "7039               True              False                  True   \n",
       "7040              False              False                  True   \n",
       "7041              False              False                  True   \n",
       "7042              False               True                  True   \n",
       "\n",
       "      PaymentMethod_Credit card (automatic)  PaymentMethod_Electronic check  \\\n",
       "0                                     False                            True   \n",
       "1                                     False                           False   \n",
       "2                                     False                           False   \n",
       "3                                     False                           False   \n",
       "4                                     False                            True   \n",
       "...                                     ...                             ...   \n",
       "7038                                  False                           False   \n",
       "7039                                   True                           False   \n",
       "7040                                  False                            True   \n",
       "7041                                  False                           False   \n",
       "7042                                  False                           False   \n",
       "\n",
       "      PaymentMethod_Mailed check  Churn_Yes  MonthlyCharges_per_tenure  \n",
       "0                          False      False                  14.925000  \n",
       "1                           True      False                   1.627143  \n",
       "2                           True       True                  17.950000  \n",
       "3                          False      False                   0.919565  \n",
       "4                          False       True                  23.566667  \n",
       "...                          ...        ...                        ...  \n",
       "7038                        True      False                   3.392000  \n",
       "7039                       False      False                   1.413699  \n",
       "7040                       False      False                   2.466667  \n",
       "7041                        True       True                  14.880000  \n",
       "7042                       False      False                   1.576866  \n",
       "\n",
       "[7043 rows x 32 columns]"
      ]
     },
     "execution_count": 7,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "feature_engineering_agent.get_data_engineered()"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "#### Feature Engineer Function"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 8,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/markdown": [
       "```python\n",
       "# Disclaimer: This function was generated by AI. Please review before using.\n",
       "# Agent Name: feature_engineering_agent\n",
       "# Time Created: 2025-01-10 08:17:47\n",
       "\n",
       "def feature_engineer(data_raw):\n",
       "    import pandas as pd\n",
       "    import numpy as np\n",
       "    from sklearn.preprocessing import OneHotEncoder, LabelEncoder\n",
       "\n",
       "\n",
       "\n",
       "    # Step 1: Convert Data Types\n",
       "    data_raw['TotalCharges'] = pd.to_numeric(data_raw['TotalCharges'], errors='coerce')\n",
       "\n",
       "    # Step 2: Remove Unique Value Features\n",
       "    data_raw.drop(columns=['customerID'], inplace=True)\n",
       "\n",
       "    # Step 3: Remove Constant Features\n",
       "    # (No constant features to remove as per the provided information)\n",
       "\n",
       "    # Step 4: Encode High Cardinality Features\n",
       "    high_cardinality_threshold = 0.05 * data_raw.shape[0]  # 5% of dataset size\n",
       "    for column in data_raw.select_dtypes(include=['object']).columns:\n",
       "        if data_raw[column].nunique() > high_cardinality_threshold:\n",
       "            # Count frequencies of each category\n",
       "            freq = data_raw[column].value_counts()\n",
       "            # Create a mask for infrequent values\n",
       "            mask = data_raw[column].isin(freq[freq >= high_cardinality_threshold].index)\n",
       "            # Replace infrequent values with 'other'\n",
       "            data_raw.loc[~mask, column] = 'other'\n",
       "\n",
       "    # Step 5: One-Hot Encoding for Categorical Variables\n",
       "    categorical_features = data_raw.select_dtypes(include=['object']).columns.tolist()\n",
       "    data_raw = pd.get_dummies(data_raw, columns=categorical_features, drop_first=True)\n",
       "\n",
       "    # Check if 'Churn' column exists before encoding\n",
       "    if 'Churn' in data_raw.columns:\n",
       "        # Step 6: Encode Target Variable\n",
       "        label_encoder = LabelEncoder()\n",
       "        data_raw['Churn'] = label_encoder.fit_transform(data_raw['Churn'])\n",
       "\n",
       "    # Step 7: Convert Boolean Features\n",
       "    # SeniorCitizen is already numeric and will be retained as is.\n",
       "    # Ensure that any potential future boolean features are converted to integers.\n",
       "\n",
       "    # Step 9: Analyze Data for Additional Features\n",
       "    # Example of creating new features:\n",
       "    data_raw['MonthlyCharges_per_tenure'] = data_raw['MonthlyCharges'] / (data_raw['tenure'] + 1)  # Avoid division by zero\n",
       "\n",
       "    # Step 10: Finalize Feature Set\n",
       "    # Return the engineered dataset\n",
       "    return data_raw\n",
       "```"
      ],
      "text/plain": [
       "<IPython.core.display.Markdown object>"
      ]
     },
     "execution_count": 8,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "feature_engineering_agent.get_feature_engineer_function(markdown=True)"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "#### Feature Engineeering Recommended Steps"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 9,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/markdown": [
       "\n",
       "\n",
       "# Recommended Feature Engineering Steps:\n",
       "1. **Convert Data Types**: Convert the `TotalCharges` column from object to float, as it contains numeric values. This will ensure that all numeric operations can be performed on this feature.\n",
       "\n",
       "2. **Remove Unique Value Features**: Remove the `customerID` column, as it has unique values equal to the size of the dataset (7043 unique values). This feature does not contribute to the prediction model.\n",
       "\n",
       "3. **Remove Constant Features**: Check for any constant features. If any exist (i.e., features with the same value in all rows), remove them. In the provided data, there are no constant features identified.\n",
       "\n",
       "4. **Encode High Cardinality Features**: Analyze categorical features and apply a threshold of 5% of the dataset size (which is 352). For high cardinality categorical features, convert infrequent values to \"other\". Check features like `PaymentMethod` and apply this transformation if necessary.\n",
       "\n",
       "5. **One-Hot Encoding for Categorical Variables**: Apply OneHotEncoding to the categorical features, such as `gender`, `Partner`, `Dependents`, `PhoneService`, `MultipleLines`, `InternetService`, `OnlineSecurity`, `OnlineBackup`, `DeviceProtection`, `TechSupport`, `StreamingTV`, `StreamingMovies`, `Contract`, and `PaperlessBilling`.\n",
       "\n",
       "6. **Encode Target Variable**: Convert the `Churn` column to numeric using Label Encoding, as it is a categorical target variable with two unique values. This will prepare it for modeling.\n",
       "\n",
       "7. **Convert Boolean Features**: Convert the `SeniorCitizen` feature (which is already numeric) to an integer type if necessary, but it is already in the correct format. Ensure that any other Boolean features that may be added in future datasets are converted to integers (1/0).\n",
       "\n",
       "8. **Create Datetime Features (if applicable)**: Check if there are any datetime columns in the dataset. If any are present, extract features such as year, month, day, etc. Since there are no datetime columns in the provided data, this step is not applicable.\n",
       "\n",
       "9. **Analyze Data for Additional Features**: Perform an analysis of the existing features to determine if there are opportunities to create new features. For instance, consider creating ratios (e.g., MonthlyCharges per tenure) or aggregating features (e.g., total services subscribed) that could enhance model performance.\n",
       "\n",
       "10. **Finalize Feature Set**: Review the engineered features and ensure that they align with the modeling goals. If all necessary transformations have been implemented and no additional features are needed, confirm the completion of the feature engineering process."
      ],
      "text/plain": [
       "<IPython.core.display.Markdown object>"
      ]
     },
     "execution_count": 9,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "feature_engineering_agent.get_recommended_feature_engineering_steps(markdown=True)"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "### Want To Become A Full-Stack Generative AI Data Scientist?\n",
    "\n",
    "![Generative AI Data Scientist](../img/become_a_generative_ai_data_scientist.jpg)\n",
    "\n",
    "I teach Generative AI Data Science to help you build AI-powered data science apps. [**Register for my next Generative AI for Data Scientists workshop here.**](https://learn.business-science.io/ai-register)"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": []
  }
 ],
 "metadata": {
  "kernelspec": {
   "display_name": "ds4b_301p_dev",
   "language": "python",
   "name": "python3"
  },
  "language_info": {
   "codemirror_mode": {
    "name": "ipython",
    "version": 3
   },
   "file_extension": ".py",
   "mimetype": "text/x-python",
   "name": "python",
   "nbconvert_exporter": "python",
   "pygments_lexer": "ipython3",
   "version": "3.10.13"
  }
 },
 "nbformat": 4,
 "nbformat_minor": 2
}
